package com.napenalki.toto.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.PostConstruct;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.napenalki.toto.domain.Team;
import com.napenalki.toto.service.EventService;
import com.napenalki.toto.service.IllegalEntryException;
import com.napenalki.toto.service.TeamService;

@Service
public class TeamServiceImpl implements TeamService, ApplicationContextAware {

    private Map<String, Team> teams;
    private Map<String, List<Team>> teamsInGroup;
    private EventService eventService;
    private ApplicationContext ctx;

    @Autowired
    public TeamServiceImpl(EventService eventService) {
        this.eventService = eventService;
    }

    @Override
    public Team getTeamByName(String teamName) {
        if (teamName == null) {
            throw new IllegalEntryException("The team name should not be null");
        }
        return teams.get(teamName);
    }

    @Override
    public List<Team> getTeamsByGroup(String group) {
        if (group == null) {
            throw new IllegalEntryException("The group should not be null");
        }
        return teamsInGroup.get(group);
    }

    @Override
    public List<Team> getGroupStandings(String group) {
        // Create a copy of the list so that we do not modify the original map
        List<Team> teamsInGroup = new ArrayList<Team>(getTeamsByGroup("G"));

        for (Team team : teamsInGroup) {
            team.setGroupMatches(eventService
                    .findCompletedGroupStageMatchesByTeam(team.getName()));
        }

        Collections.sort(teamsInGroup, Collections.reverseOrder());
        return teamsInGroup;
    }

    @PostConstruct
    public void loadTeams() throws IOException {
        File teamPropsDir = ctx.getResource("classpath:/META-INF/teams")
                .getFile();
        File[] propFiles = teamPropsDir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".properties");
            }
        });

        if (propFiles != null && propFiles.length > 0) {
            teams = new HashMap<String, Team>(32);
            teamsInGroup = new HashMap<String, List<Team>>(8);
        }
        
        for (File file : propFiles) {
            Team team = loadTeamFromFile(file);
            teams.put(team.getName(), team);
            List<Team> group = teamsInGroup.get(team.getGroup());
            if (group == null) {
                group = new ArrayList<Team>(4);
            }
            group.add(team);
            teamsInGroup.put(team.getGroup(), group);
        }
    }

    protected Team loadTeamFromFile(File file) throws IOException {
        Team team = new Team();

        Properties teamProps = new Properties();
        teamProps.load(new FileInputStream(file));

        team.setName(teamProps.getProperty("name"));
        team.setFlag(new File(file.getParent() + "/flags", file.getName()
                .substring(0, file.getName().lastIndexOf("."))
                + ".png"));
        team.setGroup(teamProps.getProperty("group"));

        String[] players = teamProps.getProperty("playerList").split(",");
        team.setPlayersList(Arrays.asList(players));

        return team;
    }

    public Map<String, Team> getTeams() {
        return teams;
    }

    public void setTeams(Map<String, Team> teams) {
        this.teams = teams;
    }

    public Map<String, List<Team>> getTeamsInGroup() {
        return teamsInGroup;
    }

    public void setTeamsInGroup(Map<String, List<Team>> teamsInGroup) {
        this.teamsInGroup = teamsInGroup;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.ctx = applicationContext;
    }
}
